//
//  Transitions.swift
//  HeadlineNews
//
//  Created by han on 2019/6/20.
//  Copyright © 2019 han. All rights reserved.
//

import UIKit

enum TransitionType {
    enum Push: String {
        case scale
        case fromRight
    }
    
    enum Present: String {
        case scale
        case fromBottom
    }
    
    enum Tab: String {
        case fromRight
    }
    
    case push(_ push: Push)
    case present(_ present: Present)
    case tab(_ tabbar: Tab)
    case none
}
enum PushOperation: Int {
    case push
    case pop
}

enum PresentOperation: Int {
    case present
    case dismiss
}

enum TabbarOperation: Int {
    case leftToRight
    case rightToLeft
}

class AnimatedTransitioning: NSObject {
    var duration = 0.35
    var transitionType: TransitionType = .none
    
    var presentOperation: PresentOperation = .present
    var tabbarOpertaion: TabbarOperation = .leftToRight
    var pushOpertaion: PushOperation = .push
    
    var isAnimation: Bool = false
    
}
// MARK: 转场动画
extension AnimatedTransitioning: UIViewControllerAnimatedTransitioning {
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return self.duration
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        
        let fromViewController = transitionContext.viewController(forKey: .from)
        let toViewController = transitionContext.viewController(forKey: .to)
        
        guard let fromView = fromViewController?.view, let toView = toViewController?.view else { return }
        switch self.transitionType {
        case .push(let type) : push(pushType: type, fromView: fromView, toView: toView, transitionContext: transitionContext)
        case .present(let type): present(presentType: type, fromView: fromView, toView: toView, transitionContext: transitionContext)
        case .tab(let type):  tab(tabType: type, fromView: fromView, toView: toView, transitionContext: transitionContext)
        default: break
        }
        
    }

}

// MARK: - tabbar
extension AnimatedTransitioning {
    func tab(tabType: TransitionType.Tab, fromView: UIView, toView: UIView, transitionContext: UIViewControllerContextTransitioning) {
        switch tabType {
        case .fromRight: tabFromRight(fromView: fromView, toView: toView, transitionContext: transitionContext)
        }
    }
    func tabFromRight(fromView: UIView, toView: UIView, transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        
        var offSet : CGVector?
        if self.tabbarOpertaion == .leftToRight {
            offSet = CGVector(dx: -1, dy: 0)
        }else{
            offSet = CGVector(dx: 1, dy: 0)
        }
        
        let fromFrame : CGRect = fromView.frame
        let toFrame : CGRect = toView.frame
        
        guard let animOffSet = offSet else { return }
        fromView.frame = fromFrame
        
        let ofDx : CGFloat = animOffSet.dx
        let ofDy : CGFloat = animOffSet.dy
        toView.frame = CGRect.offsetBy(toFrame)(dx: toFrame.size.width * ofDx * -1, dy: toFrame.size.height * ofDy * -1)
        containerView.addSubview(toView)
        self.isAnimation = true
        let transitionDuration = self.transitionDuration(using: transitionContext)
        UIView.animate(withDuration: transitionDuration, animations: { //动画
            
            fromView.frame = CGRect.offsetBy(fromFrame)(dx: fromFrame.size.width * ofDx * 1, dy: fromFrame.size.height * ofDy * 1)
            toView.frame = toFrame;
            
        }) { (_) in
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            self.isAnimation = false
        }
    }
    
}

// MARK: - push
extension AnimatedTransitioning {
    func push(pushType: TransitionType.Push, fromView: UIView, toView: UIView, transitionContext: UIViewControllerContextTransitioning) {
        switch pushType {
        case .scale: scale(fromView: fromView, toView: toView, transitionContext: transitionContext)
        case .fromRight: fromRight(fromView: fromView, toView: toView, transitionContext: transitionContext)
        }
    }
    // 当前页为带tabbar的页面，不要使用scale，会跳动。因为带有tabbar的页面，transform时的中心点变了，随后再修正回来。可以用Fram重新做一次
    func scale(fromView: UIView, toView: UIView, transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        let rect = containerView.bounds
        
        let maskView  = UIView.init(frame: rect)
        maskView.backgroundColor = UIColor.black
        
        let shadowView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: rect.height))
        shadowView.backgroundColor = UIColor.gray
        shadowView.layer.shadowOffset = CGSize(width: 0, height: 0)
        shadowView.layer.shadowRadius = 6
        shadowView.layer.shadowColor = UIColor.black.cgColor
        shadowView.layer.shadowOpacity = 0.8
    
        containerView.addSubview(toView)
        
        if self.pushOpertaion == .push {
            self.isAnimation = true
            containerView.insertSubview(maskView, belowSubview: toView)
            containerView.insertSubview(shadowView, aboveSubview: maskView)
            toView.transform = CGAffineTransform(translationX: rect.width, y: 0)
            shadowView.transform = CGAffineTransform(translationX: rect.width, y: 0)
            maskView.alpha = 0
            UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: {
                maskView.alpha = 0.8
                fromView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
                toView.transform = CGAffineTransform(translationX: 0, y: 0)
                shadowView.transform = CGAffineTransform(translationX: 0, y: 0)
            }) { (_) in
                if transitionContext.transitionWasCancelled {
                    fromView.transform = CGAffineTransform(scaleX: 1, y: 1)
                    toView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                } else {
                    fromView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
                    toView.transform = CGAffineTransform(translationX: 0, y: 0)
                    shadowView.transform = CGAffineTransform(translationX: 0, y: 0)
                }
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                maskView.removeFromSuperview()
                shadowView.removeFromSuperview()
                self.isAnimation = false
            }
        } else if self.pushOpertaion == .pop {
            self.isAnimation = true
            containerView.bringSubviewToFront(fromView)
            containerView.insertSubview(maskView, belowSubview: fromView)
            containerView.insertSubview(shadowView, aboveSubview: maskView)
            maskView.alpha = 0.8
            UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: {
                maskView.alpha = 0
                toView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
                fromView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                shadowView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                
            }) { (_) in
                if transitionContext.transitionWasCancelled {
                    toView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
                    fromView.transform = CGAffineTransform(translationX: 0, y: 0)
                } else {
                    toView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
                    fromView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                    shadowView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                }
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                maskView.removeFromSuperview()
                shadowView.removeFromSuperview()
                self.isAnimation = false
            }
        }
    }
    
    func fromRight(fromView: UIView, toView: UIView, transitionContext: UIViewControllerContextTransitioning) {
        
        let containerView = transitionContext.containerView
        let rect = containerView.bounds
        
        let maskView  = UIView.init(frame: rect)
        maskView.backgroundColor = UIColor.black
        
        let shadowView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: rect.height))
        shadowView.backgroundColor = UIColor.gray
        shadowView.layer.shadowOffset = CGSize(width: 0, height: 0)
        shadowView.layer.shadowRadius = 6
        shadowView.layer.shadowColor = UIColor.black.cgColor
        shadowView.layer.shadowOpacity = 0.8
        
        containerView.addSubview(toView)
        
        if self.pushOpertaion == .push {
            self.isAnimation = true
            containerView.insertSubview(maskView, belowSubview: toView)
            containerView.insertSubview(shadowView, aboveSubview: maskView)
            toView.transform = CGAffineTransform(translationX: rect.width, y: 0)
            shadowView.transform = CGAffineTransform(translationX: rect.width, y: 0)
            maskView.alpha = 0
            
            UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: {
                maskView.alpha = 0.8
                toView.transform = CGAffineTransform(translationX: 0, y: 0)
                shadowView.transform = CGAffineTransform(translationX: 0, y: 0)
            }) { (_) in
                if transitionContext.transitionWasCancelled {
                    toView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                } else {
                    toView.transform = CGAffineTransform(translationX: 0, y: 0)
                    shadowView.transform = CGAffineTransform(translationX: 0, y: 0)
                }
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                maskView.removeFromSuperview()
                shadowView.removeFromSuperview()
                self.isAnimation = false
            }
        } else if self.pushOpertaion == .pop {
            self.isAnimation = true
            containerView.bringSubviewToFront(fromView)
            containerView.insertSubview(maskView, belowSubview: fromView)
            containerView.insertSubview(shadowView, aboveSubview: maskView)
            maskView.alpha = 0.8
            
            UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: {
                maskView.alpha = 0
                fromView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                shadowView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                
            }) { (_) in
                if transitionContext.transitionWasCancelled {
                    fromView.transform = CGAffineTransform(translationX: 0, y: 0)
                } else {
                    fromView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                    shadowView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                }
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                maskView.removeFromSuperview()
                shadowView.removeFromSuperview()
                self.isAnimation = false
            }
        }
    }
}

// MARK: - present
extension AnimatedTransitioning {
    func present(presentType: TransitionType.Present, fromView: UIView, toView: UIView, transitionContext: UIViewControllerContextTransitioning) {
        switch presentType {
        case .scale: presentScale(fromView: fromView, toView: toView, transitionContext: transitionContext)
        case .fromBottom: presentFromBottom(fromView: fromView, toView: toView, transitionContext: transitionContext)
        }
    }
    
    func presentScale(fromView: UIView, toView: UIView, transitionContext: UIViewControllerContextTransitioning) {
        
        let containerView = transitionContext.containerView
        let rect = containerView.bounds
        
        let maskView  = UIView.init(frame: rect)
        maskView.backgroundColor = UIColor.black
        
        let shadowView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: rect.height))
        shadowView.backgroundColor = UIColor.gray
        shadowView.layer.shadowOffset = CGSize(width: 0, height: 0)
        shadowView.layer.shadowRadius = 6
        shadowView.layer.shadowColor = UIColor.black.cgColor
        shadowView.layer.shadowOpacity = 0.8
        
        containerView.addSubview(toView)
        
        if self.presentOperation == .present{
            self.isAnimation = true
            containerView.insertSubview(maskView, belowSubview: toView)
            containerView.insertSubview(shadowView, aboveSubview: maskView)
            toView.transform = CGAffineTransform(translationX: rect.width, y: 0)
            shadowView.transform = CGAffineTransform(translationX: rect.width, y: 0)
            maskView.alpha = 0
            UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: {
                maskView.alpha = 0.8
                fromView.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
                toView.transform = CGAffineTransform(translationX: 0, y: 0)
                shadowView.transform = CGAffineTransform(translationX: 0, y: 0)
            }) { (_) in
                if transitionContext.transitionWasCancelled {
                    fromView.transform = CGAffineTransform(scaleX: 1, y: 1)
                    toView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                } else {
                    fromView.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
                    toView.transform = CGAffineTransform(translationX: 0, y: 0)
                    shadowView.transform = CGAffineTransform(translationX: 0, y: 0)
                }
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                maskView.removeFromSuperview()
                shadowView.removeFromSuperview()
                self.isAnimation = false
            }
        } else if self.presentOperation == .dismiss {
            self.isAnimation = true
            containerView.bringSubviewToFront(fromView)
            containerView.insertSubview(maskView, belowSubview: fromView)
            containerView.insertSubview(shadowView, aboveSubview: maskView)
            maskView.alpha = 0.8
            UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: {
                maskView.alpha = 0
                toView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
                fromView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                shadowView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                
            }) { (_) in
                if transitionContext.transitionWasCancelled {
                    fromView.transform = CGAffineTransform(translationX: 0, y: 0)
                } else {
                    fromView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                    shadowView.transform = CGAffineTransform(translationX: rect.width, y: 0)
                }
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                maskView.removeFromSuperview()
                shadowView.removeFromSuperview()
                self.isAnimation = false
            }
        }
    }
    
    func presentFromBottom(fromView: UIView, toView: UIView, transitionContext: UIViewControllerContextTransitioning) {
        if self.presentOperation == .present {
            self.isAnimation = true
            transitionContext.containerView.addSubview(toView)
            
            toView.transform = CGAffineTransform(translationX: 0,
                                                 y: toView.frame.height)
            
            UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: {
                toView.transform = CGAffineTransform(translationX: 0, y: 0)
                fromView.alpha = 0.6
                
            }) { (_) in
                toView.transform = CGAffineTransform(translationX: 0, y: 0)
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                self.isAnimation = false
            }
        } else if self.presentOperation == .dismiss {
            self.isAnimation = true
            UIView.animate(withDuration: self.transitionDuration(using: transitionContext), animations: {
                fromView.transform = CGAffineTransform(translationX: 0,
                                                       y: fromView.frame.height)
                toView.alpha = 1.0
                
            }) { (_) in
                if transitionContext.transitionWasCancelled {
                    fromView.transform = CGAffineTransform(translationX: 0, y: 0)
                } else {
                    fromView.transform = CGAffineTransform(translationX: 0,
                                                           y: fromView.frame.height)
                }
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                self.isAnimation = false
            }
        }
    }
}




